﻿using System;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using Castle.MonoRail.Framework;
using Castle.MonoRail.Framework.Filters;
using StateTheater.Models;
using StateTheaterDataModel;
using Castle.Core;
using System.Collections.Generic;
using Castle.MonoRail.Framework.Helpers;
using System.Security.Principal;

namespace StateTheater.Controllers
{
	[Layout("default"), Rescue("generalerror")]
	[Filter(ExecuteWhen.BeforeAction, typeof(MobileFilter))]
	public class VenueController : SmartDispatcherController
	{

		private readonly Status OK = new Status("OK");
		private readonly Status BAD = new Status("BAD");

		StateTheaterDataContext db;
		public VenueController(StateTheaterDataContext db)
		{
			this.db = db;
		}

		public void Display(int id)
		{
			Display(ven => ven.VenueID == id);
		}

		public void Display(string name)
		{
			Display(ven => ven.Shortname == name);
		}

		public void Display(Expression<Func<Venue, bool>> whereClause)
		{
			Venue venue = db.Venues.Where(whereClause).FirstOrDefault();
			if (venue == null)
				throw new ArgumentOutOfRangeException();

			PropertyBag["Venue"] = venue;
			PropertyBag["VenueName"] = Util.AdjTitle(venue.Name);
			PropertyBag["ZipCode"] = venue.ZipCode.Substring(0, 5);
			string address = "{0}, {1}, {2} {3}".With((venue.Address2 ?? venue.Address1), venue.City, venue.State, venue.ZipCode);

			if (venue.lat.HasValue)
			{
				string mapurl = string.Format("	var latLong = new VELatLong({0}, {1});", venue.lat.Value, venue.lng.Value);
				PropertyBag["mapLatLong"] = mapurl;
			}
			PropertyBag["mapAddress"] = address;

			// Troupes by Venue
			var q = (from p in db.Productions
					 where p.VenueID == venue.VenueID
					 //					 select new Pair<string, string>(p.Troupe.shortname, Util.AdjTitle(p.Troupe.Name))
					 select new { Name = Util.AdjTitle(p.Troupe.Name), Code= p.Troupe.shortname, ID=p.Troupe.TroupeID }
					).Distinct();

			var troupes = q.ToList();
			if (troupes.Count > 0)
			{
				PropertyBag["troupes"] = troupes;
			}
			string user = this.Context.CurrentUser.Identity.Name;
			bool isAdmin = this.Context.CurrentUser.IsInRole("Admin");

			var isTroupePerm = from tp in db.TroupePermissions
					join  pr in db.Productions 
					on  tp.Troupeid equals pr.TroupeID 
					where tp.FORUM_MEMBER.M_NAME==user && pr.VenueID == venue.VenueID
					select pr;

			if (isAdmin || isTroupePerm.Any())
			{
				PropertyBag["allowEdit"] = true;
			}


		}

		public void Add()
		{
			Edit(0);
		}

		public void Edit(int id)
		{
			var venue = db.Venues.FirstOrDefault(v => v.VenueID == id);
			if (venue == null)
				venue = new Venue();
			PropertyBag["venue"] = venue;

			AdminController.GetCounties(PropertyBag, db);
		}
		public void Save([DataBind("venue")] Venue venue)
		{
			Venue v = null;
			if (venue.VenueID != 0)
			{
				v = db.Venues.FirstOrDefault(vv => vv.VenueID == venue.VenueID);
				PropertyBag["action"] = "edited";
			}
			else
			{
				v = new Venue();
				db.Venues.InsertOnSubmit(v);
				PropertyBag["action"] = "added";
			}

			v.Address1 = venue.Address1;
			v.Address2 = venue.Address2;
			v.City = venue.City;
			v.Comments = venue.Comments ?? "";
			v.Name = venue.Name;
			v.Shortname = venue.Shortname;
			v.State = venue.State;
			v.ZipCode = venue.ZipCode;

			var loc = db.Locations.FirstOrDefault(l => l.ZipCode == venue.ZipCode);
			var cnty = this.Query["venCounties"] as string;
			if (loc != null && String.IsNullOrEmpty(loc.City) && !String.IsNullOrEmpty(cnty))
			{
				int cntyNum = Convert.ToInt32(cnty);
				if (cntyNum != 0)
				{
					loc.City = venue.City;
					loc.County = cntyNum;
					loc.CountyLet = db.Counties.Single(c => c.CodeNum == cntyNum).CodeLet;
				}
			}
			db.SubmitChanges();

			PropertyBag["venue"] = v;
			AdminController.RecordUserAction(db, this, "editvenue", venue.VenueID, PropertyBag);
		}

		public void Info(int VenueId)
		{
			CancelLayout();

			PropertyBag["venue"] = (db.Venues.Where(v => v.VenueID == VenueId)).FirstOrDefault();
		}

		// ----- Web Services

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public SelectList[] VenuesForProduction(int TroupeID, int ProductionID)
		{
			List<SelectList> selectList = null;
			if (ProductionID == 0)
			{
				selectList = (from pr in db.Productions
							  where pr.TroupeID == TroupeID
                              let prefVenueID = pr.Troupe.VenueID ?? 0
							  select new SelectList
							  {
								  id = pr.Venue.VenueID.ToString(),
								  label = pr.Venue.Name,
                                  selected = (pr.Venue.VenueID == prefVenueID)
							  }).Distinct().ToList();
			}
			else
			{
				selectList = (from pr in db.Productions
							  where pr.TroupeID == TroupeID
							  select new SelectList
							  {
								  id = pr.Venue.VenueID.ToString(),
								  label = pr.Venue.Name,
								  selected = (pr.ProductionID == ProductionID)
							  }).Distinct().ToList();
			}

			selectList.Add(new SelectList("(not listed)", "0"));

			return selectList.ToArray();
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public SelectList[] ForCountyJson(int lstCounties)
		{
			var venues = (from v in db.Venues
						  where v.Location.County == lstCounties
						  orderby v.City, v.Name
						  select new SelectList
						  {
							  id = v.VenueID.ToString(),
							  label = v.City + " - " + v.Name
						  }).ToArray();

			return venues;
		}

		public class MiniLoc
		{
			public string City { get; set; }
			public string State { get; set; }
			public int? County { get; set; }
		}


		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public MiniLoc CountyFromZip(string zip)
		{
			var loc = (from l in db.Locations
					   where l.ZipCode == zip
					   select new MiniLoc
					   {
						   City = l.City,
						   State = "NJ",
						   County = l.County
					   }).FirstOrDefault();
			if (loc == null || !loc.County.HasValue)
				return new MiniLoc { City = "", County = 0, State = "" };
			return loc;
		}

		[return:JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status SaveLocation(string zip, string city, int county)
		{
			var loc = db.Locations.FirstOrDefault(l => l.ZipCode == zip);
			if (loc != null)
			{
				loc.City = city;
				loc.County = county;
				loc.CountyLet = db.Counties.First(c => c.CodeNum == county).CodeLet;
				db.SubmitChanges();
			}

			return OK;
		}
	}
}
